package com.ossjk.qlh.loginfo;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.ossjk.core.constant.Constant;
import com.ossjk.core.util.HttpUtil;
import com.ossjk.qlh.system.entity.Loginfo;
import com.ossjk.qlh.system.service.ILoginfoService;

@Aspect
@Component
public class LogInfoAspect {
	@Autowired
	private ILoginfoService iLoginfoService;

	@Around("@within(com.ossjk.qlh.loginfo.LogModule) and @annotation(com.ossjk.qlh.loginfo.LogOperation)")
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

		Signature signature = proceedingJoinPoint.getSignature();
		MethodSignature msig = null;
		if (!(signature instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) signature;
		Object target = proceedingJoinPoint.getTarget();
		Class targetClass = target.getClass();
		// 获取类注解
		LogModule logModule = (LogModule) targetClass.getAnnotation(LogModule.class);
		// 尝试获取方法
		Method currentMethod = targetClass.getMethod(msig.getName(), msig.getParameterTypes());
		// 获取方法的注解
		LogOperation logOperation = currentMethod.getAnnotation(LogOperation.class);
		// 获取请求
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// IP
		String ip = HttpUtil.getIp(request);
		// UserAgent
		String userAgent = HttpUtil.getUserAgent(request);
		// uid
		String uid = (String) request.getAttribute(Constant.REQUEST_ATTRIBUTE_UID);

		Loginfo loginfo = new Loginfo();
		loginfo.setIp(ip);
		loginfo.setUseragent(userAgent);
		loginfo.setOptime(new Date());
		loginfo.setUid(uid);
		loginfo.setModule(logModule.value());
		loginfo.setUri(request.getRequestURI());
		loginfo.setOperation(logOperation.value());
		loginfo.setContent(JSON.toJSONString(proceedingJoinPoint.getArgs()));
		// 日志类型 1-业务、2-错误信息
		loginfo.setType(1);
		iLoginfoService.save(loginfo);
		Object result = proceedingJoinPoint.proceed();
		return result;
	}

	@AfterThrowing(value = "@within(com.ossjk.qlh.loginfo.LogModule) and @annotation(com.ossjk.qlh.loginfo.LogOperation)", throwing = "exception")
	public void afterThrowing(JoinPoint joinPoint, Exception exception) throws Throwable {

		Signature signature = joinPoint.getSignature();
		MethodSignature msig = null;
		if (!(signature instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) signature;
		Object target = joinPoint.getTarget();
		Class targetClass = target.getClass();
		// 获取类注解
		LogModule logModule = (LogModule) targetClass.getAnnotation(LogModule.class);
		// 尝试获取方法
		Method currentMethod = targetClass.getMethod(msig.getName(), msig.getParameterTypes());
		// 获取方法的注解
		LogOperation logOperation = currentMethod.getAnnotation(LogOperation.class);
		// 获取请求
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// IP
		String ip = HttpUtil.getIp(request);
		// UserAgent
		String userAgent = HttpUtil.getUserAgent(request);
		// uid
		String uid = (String) request.getAttribute(Constant.REQUEST_ATTRIBUTE_UID);
		Loginfo loginfo = new Loginfo();
		loginfo.setIp(ip);
		loginfo.setUseragent(userAgent);
		loginfo.setOptime(new Date());
		loginfo.setUid(uid);
		loginfo.setModule(logModule.value());
		loginfo.setUri(request.getRequestURI());
		loginfo.setOperation(logOperation.value());
		loginfo.setContent(exception.toString());
		// 日志类型 1-业务、2-错误信息
		loginfo.setType(2);
		iLoginfoService.save(loginfo);
	}

}